package com.iplant.base.controller;

import java.text.MessageFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.iplant.base.po.BasePO;
import com.iplant.base.utils.annotation.po.DBBasePO;
import com.iplant.base.utils.sql.orm.ORMUtils;
import com.iplant.base.utils.sql.orm.POUtils;
import com.iplant.base.utils.sql.orm.PoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.iplant.base.po.BaseUser;
import com.iplant.base.po.Pagination;
import com.iplant.base.utils.SessionConstants;
import com.iplant.base.utils.general.DesUtil;
import com.iplant.base.utils.general.StringUtils;
import com.iplant.base.utils.general.URIUtil;

public class BaseController {

    private static Logger logger = LoggerFactory.getLogger(BaseController.class);

    public static String RESULT_KEY = "resultCode";

    private static String RESULT_MSG = "msg";

    private static String RESULT_RETURN = "returnObject";

    private static String DATA_LIST = "list";

    private static String DATA_INFO = "info";

    private static String REQUEST_PO = "BasePO_Name";
    public static Map<String, Class<? extends BasePO>> BasePOClassMap = new HashMap<>();


    protected Class<? extends BasePO> GetBasePOClass(String wClassName) {
        if (wClassName != null && BasePOClassMap.containsKey(wClassName))
            return BasePOClassMap.get(wClassName);

        return null;
    }


    protected Class<? extends BasePO> GetBasePOClass(Map<String, Object> wParam) {

        if (wParam == null || wParam.size() == 0 || !wParam.containsKey(REQUEST_PO))
            return null;
        String wBasePOName = StringUtils.parseString(wParam.get(REQUEST_PO));

        return GetBasePOClass(wBasePOName);
    }


    protected PoService<? extends BasePO> GetPoService(Map<String, Object> wParam) {

        Class<? extends BasePO> wClazz = GetBasePOClass(wParam);
        if (wClazz == null)
            return null;
        return ORMUtils.GetPoService(wClazz);
    }

    protected PoService<? extends BasePO> GetPoService(String wClassName) {

        Class<? extends BasePO> wClazz = GetBasePOClass(wClassName);
        if (wClazz == null)
            return null;
        return ORMUtils.GetPoService(wClazz);
    }


    /**
     * 获取返回ReturnObject
     **/

    protected static Map<String, Object> GetReturnObject(String wMsg, Object wReturnObjectList,
                                                         Object wReturnObjectInfo) {
        Map<String, Object> wResult = new HashMap<String, Object>();
        wResult.put(RESULT_MSG, wMsg);
        wResult.put(DATA_LIST, wReturnObjectList);
        wResult.put(DATA_INFO, wReturnObjectInfo);
        return wResult;
    }

    public static String GetProjectName(HttpServletRequest request) {
        String wResult = "";

        String wURL = request.getRequestURL().toString();
        if (wURL.indexOf("/api/") < 0)
            return wResult;

        wURL = wURL.substring(0, wURL.indexOf("/api/"));
        wResult = wURL;
        if (wURL.indexOf(":") < 0)
            return wResult;

        if (wURL.lastIndexOf("/") < wURL.lastIndexOf(":"))
            return "";

        wResult = wURL.substring(wURL.lastIndexOf("/"));

        return wResult;
    }

    public static String GetRealProjectName(HttpServletRequest request) {
        String wResult = "";

        String wURL = request.getHeader("X-Original-Path");

        if (StringUtils.isEmpty(wURL) || wURL.length() < 5)
            wURL = request.getRequestURL().toString();

        if (wURL.indexOf("/api/") < 0)
            return wResult;

        wURL = wURL.substring(0, wURL.indexOf("/api/"));
        wResult = wURL;
        if (wURL.indexOf(":") < 0)
            return wResult;

        if (wURL.lastIndexOf("/") < wURL.lastIndexOf(":"))
            return "";

        wResult = wURL.substring(wURL.lastIndexOf("/"));

        return wResult;
    }

    public static String GetApiName(HttpServletRequest request) {
        String wResult = "";

        String wURL = request.getRequestURI();
        if (wURL.indexOf("/api/") < 0)
            return wResult;

        return wURL.substring(wURL.indexOf("/api/") + 5);
    }

    /**
     * 特殊处理返回 可修改ReturnObject后返回
     **/

    public static Map<String, Object> GetResult(int wResultCode, Map<String, Object> wReturnObject) {
        Map<String, Object> wResult = new HashMap<String, Object>();
        wResult.put(RESULT_KEY, wResultCode);
        wResult.put(RESULT_RETURN, wReturnObject);
        return wResult;
    }

    /**
     * 普通返回
     **/

    public static Map<String, Object> GetResult(int wResultCode, String wMsg, Object wReturnObjectList,
                                                Object wReturnObjectInfo) {

        return GetResult(wResultCode, GetReturnObject(wMsg, wReturnObjectList, wReturnObjectInfo));
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> SetResult(Map<String, Object> wResult, String wObjectName, Object wObject) {
        if (wResult.containsKey(RESULT_RETURN)) {
            ((Map<String, Object>) wResult.get(RESULT_RETURN)).put(wObjectName, wObject);
        }

        return wResult;
    }

    /**
     * 报错返回
     **/

    public static Map<String, Object> GetResult(int wResultCode, String wMsg) {
        return GetResult(wResultCode, GetReturnObject(wMsg, null, null));
    }

    @Deprecated
    public static boolean CheckCookieEmpty(HttpServletRequest wRequest) {
        Boolean wRst = false;

        HttpSession session = wRequest.getSession();
        BaseUser wBMSEmployee = new BaseUser();
        if (session.getAttribute(SessionConstants.SessionUser) != null) {
            wBMSEmployee = (BaseUser) session.getAttribute(SessionConstants.SessionUser);
            if (wBMSEmployee == null)
                wBMSEmployee = new BaseUser();
        }
        if (wBMSEmployee.getID() <= 0 && wBMSEmployee.getID() != -100) {
            String wLoginName = getCookieValue(SessionConstants.CookieUser, wRequest);
            String wID = getCookieValue(SessionConstants.CookieUserID, wRequest);
            if (StringUtils.isEmpty(wID)) {

                wRst = true;
            } else {
                wBMSEmployee.ID = StringUtils.parseInt(wID);
            }
            if (StringUtils.isEmpty(wLoginName)) {
                wRst = true;
            } else {
                wBMSEmployee.LoginName = wLoginName;
            }
            session.setAttribute(SessionConstants.SessionUser, wBMSEmployee);
        }
        if (wBMSEmployee.getID() <= 0 && wBMSEmployee.getID() != -100) {
            wRst = true;
        }
        return wRst;

    }

    public static BaseUser GetSessionBase(HttpServletRequest wRequest) {
        BaseUser wBMSEmployee = new BaseUser();
        HttpSession session = wRequest.getSession();
        if (session.getAttribute(SessionConstants.SessionUser) != null) {
            wBMSEmployee = (BaseUser) session.getAttribute(SessionConstants.SessionUser);
            if (wBMSEmployee == null)
                wBMSEmployee = new BaseUser();
        }
        return wBMSEmployee;
    }

    @SuppressWarnings("unchecked")
    public static <T extends BaseUser> T GetSession(HttpServletRequest wRequest, Class<T> clazz) {
        T wBMSEmployee = null;
        HttpSession session = wRequest.getSession();
        if (session.getAttribute(SessionConstants.SessionUser) != null) {
            wBMSEmployee = (T) session.getAttribute(SessionConstants.SessionUser);
        }
        if (wBMSEmployee == null) {
            try {
                wBMSEmployee = clazz.newInstance();
            } catch (Exception e) {
                logger.error("GetSession ", e);
            }
        }

        return wBMSEmployee;
    }

    @SuppressWarnings("unchecked")
    public static <T extends BaseUser> T GetSession(HttpServletRequest wRequest) {
        T wBMSEmployee = null;
        HttpSession session = wRequest.getSession();
        if (session.getAttribute(SessionConstants.SessionUser) != null) {
            wBMSEmployee = (T) session.getAttribute(SessionConstants.SessionUser);
        }

        return wBMSEmployee;
    }

    public static Map<String, Object> GetParamsMap(HttpServletRequest wRequest) {
        Map<String, Object> wParams = new HashMap<>();

        if (wRequest == null || wRequest.getParameterMap() == null || wRequest.getParameterMap().size() == 0) {
            return wParams;
        }
        Map<String, String[]> wParameterMap = wRequest.getParameterMap();

        for (String wKey : wParameterMap.keySet()) {
            wParams.put(wKey, wRequest.getParameter(wKey));
        }
        return wParams;
    }


    public static Pagination GetPagination(HttpServletRequest wRequest) {

        int wPageIndex = StringUtils.parseInt(wRequest.getParameter("PageIndex"));
        int wPageSize = StringUtils.parseInt(wRequest.getParameter("PageSize"));

        String wPageSort = StringUtils.parseString(wRequest.getParameter("PageSort"));
        String wPageSortType = StringUtils.parseString(wRequest.getParameter("PageSortType"));

        String wPageFuzzy = StringUtils.parseString(wRequest.getParameter("PageFuzzy"));

        return Pagination.Create(wPageIndex, wPageSize, wPageSort, wPageSortType, wPageFuzzy);
    }

    public static Pagination GetPagination(HttpServletRequest wRequest, String... wValues) {

        int wPageIndex = StringUtils.parseInt(wRequest.getParameter("PageIndex"));
        int wPageSize = StringUtils.parseInt(wRequest.getParameter("PageSize"));

        String wPageSort = StringUtils.parseString(wRequest.getParameter("PageSort"));
        String wPageSortType = StringUtils.parseString(wRequest.getParameter("PageSortType"));

        String wPageFuzzy = StringUtils.parseString(wRequest.getParameter("PageFuzzy"));
        if (wValues == null && wValues.length > 0) {
            if (StringUtils.isEmpty(wPageSort))
                wPageSort = wValues[0];
            if (wValues.length > 1) {
                if (StringUtils.isEmpty(wPageSortType))
                    wPageSort = wValues[1];
            }
        }

        return Pagination.Create(wPageIndex, wPageSize, wPageSort, wPageSortType, wPageFuzzy);
    }

    public static Pagination GetPagination(HttpServletRequest wRequest, Class<? extends BasePO> clazz) {

        int wPageIndex = StringUtils.parseInt(wRequest.getParameter("PageIndex"));
        int wPageSize = StringUtils.parseInt(wRequest.getParameter("PageSize"));

        String wPageSort = StringUtils.parseString(wRequest.getParameter("PageSort"));
        String wPageSortType = StringUtils.parseString(wRequest.getParameter("PageSortType"));
        String wPageFuzzy = StringUtils.parseString(wRequest.getParameter("PageFuzzy"));
        if (StringUtils.isEmpty(wPageSort)) {
            DBBasePO dbBasePO = POUtils.GetInstance().getDBBasePO(clazz);
            if (dbBasePO != null && StringUtils.isNotEmpty(dbBasePO.OrderBy())) {
                wPageSort = dbBasePO.OrderBy();
            }
        }

        return Pagination.Create(wPageIndex, wPageSize, wPageSort, wPageSortType, wPageFuzzy);
    }

    public static void RemoveSession(HttpServletRequest wRequest) {
        HttpSession session = wRequest.getSession();
        if (session.getAttribute(SessionConstants.SessionUser) != null) {
            wRequest.getSession().removeAttribute(SessionConstants.SessionUser);
        }
    }

    public static void RemoveCookie(HttpServletRequest wRequest, HttpServletResponse wResponse) {
        Cookie[] cookies = wRequest.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                cookie.setValue(null);
                cookie.setMaxAge(0);// 立即销毁cookie
                cookie.setPath("/");
                wResponse.addCookie(cookie);
            }
        }
    }

    public static void SetSession(HttpServletRequest wRequest, BaseUser wBMSEmployee) {
        SetSession(wRequest, wBMSEmployee, 1800);
    }

    public static void SetSession(HttpServletRequest wRequest, BaseUser wBMSEmployee, int wSecond) {
        if (wBMSEmployee == null)
            return;
        if (wRequest.getSession().getAttribute(SessionConstants.SessionUser) != null) {
            wRequest.getSession().removeAttribute(SessionConstants.SessionUser);
        }
        wRequest.getSession().setAttribute(SessionConstants.SessionUser, wBMSEmployee);
        wRequest.getSession().setMaxInactiveInterval(wSecond);
    }

    public static void SetCookie(HttpServletRequest wRequest, HttpServletResponse wResponse, BaseUser wBMSEmployee) {
        SetCookie(wRequest, wResponse, wBMSEmployee, -1);
    }

    public static void SetCookie(HttpServletRequest wRequest, HttpServletResponse wResponse, BaseUser wBMSEmployee, int wSecond) {
        if (wBMSEmployee == null)
            return;

        RemoveCookie(wRequest, wResponse);

        Cookie co = new Cookie(SessionConstants.CookieUser, wBMSEmployee.getLoginName());

        co.setPath("/");
        co.setMaxAge(wSecond);
        wResponse.addCookie(co);

        Cookie co1 = new Cookie(SessionConstants.CookieUserID,
                DesUtil.encrypt(String.valueOf(wBMSEmployee.getID()), SessionConstants.appSecret));

        co1.setPath("/");
        co1.setMaxAge(wSecond);
        wResponse.addCookie(co1);
    }

    public static String getCookieValue(String cookie_key, HttpServletRequest request) {

        String cookie_val = null;
        Cookie[] cos = request.getCookies();
        if (cos != null && cos.length > 0) {
            for (Cookie co : cos) {
                if (cookie_key.equalsIgnoreCase(co.getName())) {
                    cookie_val = co.getValue();
                    break;
                }
            }

        } else {
            cookie_val = StringUtils.parseString(request.getAttribute(cookie_key));
        }
        if (StringUtils.isEmpty(cookie_val)) {
            return cookie_val;
        }
        if (cookie_val.contains("%"))
            cookie_val = URIUtil.decodeURIComponent(cookie_val);

        try {
            cookie_val = DesUtil.decrypt(cookie_val, SessionConstants.appSecret);
        } catch (Exception e) {

            logger.error("getCookieValue", e);
        }

        return cookie_val;
    }

    public static String getCookieEnValue(String cookie_key, HttpServletRequest request) {

        String cookie_val = null;
        Cookie[] cos = request.getCookies();
        if (cos != null && cos.length > 0) {
            for (Cookie co : cos) {
                if (cookie_key.equalsIgnoreCase(co.getName())) {
                    cookie_val = co.getValue();
                    break;
                }
            }
        } else {
            cookie_val = StringUtils.parseString(request.getAttribute(cookie_key));
        }
        if (StringUtils.isEmpty(cookie_val)) {
            return cookie_val;
        }
        if (cookie_val.contains("%"))
            cookie_val = URIUtil.decodeURIComponent(cookie_val);

//		try {
//			cookie_val = DesUtil.decrypt(cookie_val, SessionConstants.appSecret);
//		} catch (Exception e) {
//
//			logger.error("getCookieValue", e);
//		}

        return cookie_val;
    }

    public static String CreateToken(String account) {
        String wToken = "";

        try {
            String wT4 = account.substring(0, account.length() / 2);
            String wT2 = account.substring(account.length() / 2);
            String wT3 = MessageFormat.format("{0}-{1}", String.valueOf(Calendar.getInstance().get(Calendar.YEAR)),
                    String.format("%02d", Calendar.getInstance().get(Calendar.MONTH) + 1));
            String wT5 = String.format("%02d", Calendar.getInstance().get(Calendar.DAY_OF_MONTH));
            String wT1 = MessageFormat.format("{0}:{1}:{2}",
                    String.format("%02d", Calendar.getInstance().get(Calendar.HOUR_OF_DAY)),
                    String.format("%02d", Calendar.getInstance().get(Calendar.MINUTE)),
                    String.format("%02d", Calendar.getInstance().get(Calendar.SECOND)));

            wToken = MessageFormat.format("{0}+-abc072-+{1}+-abc072-+{2}+-abc072-+{3}+-abc072-+{4}", wT1, wT2, wT3, wT4,
                    wT5);

            wToken = DesUtil.encrypt(wToken, SessionConstants.appSecret);
        } catch (Exception e) {
            logger.error("CreateToken", e);
        }

        return wToken;
    }

}
